using System;
using System.Collections.Generic;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Framework.Serialization;
using IQIGame.Onigao.GamePlay;
using Newtonsoft.Json;

namespace IQIGame.Onigao.Logic
{
    public class StoryConfig : SerializeCustomConfig
    {
        public EStoryType storyType;
        public List<StoryNodeConfig> nodes = new List<StoryNodeConfig>();
        public bool hasService;
        public bool has3D;
        public string synopsis; // 故事简介

        private Dictionary<int, int> id2Index = new Dictionary<int, int>();

#if UNITY_EDITOR
        [JsonIgnore]
        public Action onBeforeSerialize { get; set; }
#endif

        public StoryNodeConfig GetNode(int id)
        {
            return this.nodes[this.GetIndex(id)];
        }

        public int GetIndex(int id)
        {
#if UNITY_EDITOR
            if (StoryClientUtil.IsEditorMode)
            {
                return this.nodes.FindIndex((rNode) => rNode.id == id);
            }
#endif
            return this.id2Index[id];
        }

        // 注意 下面的部分只有反序列化代码允许在runtime时运行
        public static StoryConfig Parse(string json)
        {
            var rConfig = JsonHelper.DeserializeJson<StoryConfig>(json);
            return rConfig;
        }

        public static string ToJson(StoryConfig config)
        {
            config.SetPropertyBeforeSerialize();
            return JsonHelper.SerializeObject(config);
        }

        public override void Serialize(ByteBuf _buf)
        {
            this.SetPropertyBeforeSerialize();
            _buf.SerializeList(this.nodes);
            _buf.WriteInt((int)this.storyType);
            _buf.WriteBool(this.hasService);
            _buf.WriteBool(this.has3D);
            _buf.WriteString(this.synopsis);
        }

        public override void DeSerialize(ByteBuf _buf)
        {
            this.nodes = _buf.DeSerializeList<StoryNodeConfig>();
            this.storyType = (EStoryType)_buf.ReadInt();
            this.hasService = _buf.ReadBool();
            this.has3D = _buf.ReadBool();
            this.synopsis = _buf.ReadString();
            for (int i = 0; i < this.nodes.Count; i++)
            {
                var rNode = this.nodes[i];
                this.id2Index[rNode.id] = i;
            }
        }

        private void SetPropertyBeforeSerialize()
        {
            // 记录有没有服务
            this.hasService = this.nodes.Exists((rNode) =>
            {
                return (rNode.customConfig.TryGetValue(EStoryNodeType.Option, out var rConfig) &&
                        rConfig is StoryNode_Option rOption &&
                        rOption.choose.Exists((x) => x.service?.Count > 0)) ||
                       (rNode.customConfig.TryGetValue(EStoryNodeType.End, out var rEndConfig) &&
                        rEndConfig is StoryNode_End rEnd &&
                        rEnd.service.Count > 0);
            });

            this.has3D = this.nodes.Exists((rNode) => rNode.customConfig.TryGetValue(EStoryNodeType.Timeline, out var rConfig) && rConfig is StoryNode_Timeline);

#if UNITY_EDITOR
            // 部分代码需要在editor实现，使用action
            this.onBeforeSerialize?.Invoke();
#endif
        }
    }

    public class StoryNodeConfig : SerializeCustomConfig
    {
        public int id;
        public string remark;
        public float autoWait;
        /// <summary>
        /// 当前剧情节点直接跳转的下一个节点id
        /// 有选项时无效，以选项里的jumpId为准
        /// </summary>
        public int directJumpID;

        // 指定顺序，按照type排序，在设置表现内容时，选项的设置需要在nor之后
        public SortedDictionary<EStoryNodeType, SerializeCustomConfig> customConfig = new();

        public override string ToString()
        {
            return $"{this.id}:{this.remark}";
        }

        public override void Serialize(ByteBuf _buf)
        {
            _buf.WriteInt(this.id);
            _buf.WriteString(this.remark);
            _buf.WriteInt(this.directJumpID);
            _buf.WriteFloat(this.autoWait);

            _buf.WriteInt(this.customConfig.Count);
            foreach (var rPair in this.customConfig)
            {
                _buf.WriteInt((int)rPair.Key);
                _buf.SerializeObject(rPair.Value);
            }
        }

        public override void DeSerialize(ByteBuf _buf)
        {
            this.id = _buf.ReadInt();
            this.remark = _buf.ReadString();
            this.directJumpID = _buf.ReadInt();
            this.autoWait = _buf.ReadFloat();

            var nParamCount = _buf.ReadInt();
            for (int i = 0; i < nParamCount; i++)
            {
                var rType = (EStoryNodeType)_buf.ReadInt();
                var rConfig = rType.CreateNodeConfig();
                _buf.DeSerializeObject(ref rConfig);
                try
                {
                    this.customConfig.Add(rType, rConfig);
                }
                catch (Exception e)
                {
                    LogGame.LogError($"加载剧情{this.id}失败" + e);
                }
            }
        }
    }

    public enum EStoryNodeType
    {
        Normal = 0,
        Option = 1,
        End = 2,
        Timeline = 3,
        // SpeakerImage = 4,
        // Live2D = 5,
        RemoveSpeaker = 6,
        Effect = 7,
        CenterContents = 8,
        Speaker = 9,
        Bgm = 10,
        Video = 11,
        BackgroundAction = 12,

        Max,
    }

    public enum EStoryType
    {
        Common,
        Level,
        MainCity,
        Battle
    }
}